package java_thinking.unit_8._8_2;

/**
 * @Description : 多态
 *                继承是多态得以实现的基础,将一个方法调用同这个方法所属的主题（也就是对象或类）关联起来叫做绑定
 *                绑定分为：前期绑定和后期绑定。
 *                1.前期绑定：在程序运行之前进行绑定，由编译器和连接程序实现，又叫做静态绑定。比如static方法和final方法。注意，这里也包括private方法，因为他是隐式final的。
 *                2.后期绑定：在运行时根据对象的类型进行绑定。由调用机制实现，因此又叫做动态绑定，或运行时绑定。除了前期绑定之外的所有方法都属于后期绑定。
 *                当我们用父子关系实现多态的时候和用接口实现多态的时候，概念是不同的
 *                多态又分为 编译时多态和运行时多态。
                 *编译时多态：比如重载
                 *运行时多态：比如重写
 *
 *                1.接口的多种不同的实现方式即为多态。
 *                2.多态性是允许你将父对象设置成为一个或更多的他的子对象相等的技术。
 *                3.我们在程序中定义的引用变量所指向的具体类-和该引用变量的方法调用在编程的时候并不确定，
 *                  当处于运行期间才确定。就是这个引用变量究竟指向哪一个实例对象，在编译期间是不确定的
 *                  ，只有运行期才能确定，这样不用修改源码就可以把变量绑定到不同的类实例上，
 *                  让程序拥有了多个运行状态，这就是多态。
 *
 * 多态的实现机制
 *                1.静态分派:所有依赖静态类型来定位方法执行版本的分派动作。静态分派发生在编译阶段，因此确定静态分派的动作实际
 *                  上不是由虚拟机来执行的，而是由编译器来完成。（编译时多态）
 *                2.动态分派：在运行期根据实际类型确定方法执行版本的分派动作。（运行时多态）
 * @author: cww
 * @DateTime: 2019/2/28 18:59
 */
enum  Note{
    MIDDLE_A,MIDDEL_B,MIDDLE_C
}

class Instrument {
    void play(Note n){
        System.out.println("Instrument.play() "+n);
    }
    String whatObject(){
        return "Instrument";
    }
    public String toString(){
        return "Instrument";
    }
    void adjust(){
        System.out.println("Adjusting Instrument");
    }
}

class Wind extends Instrument{
    void play(Note n){
        System.out.println("Wind.play() "+n);
    }
    String whatObject(){
        return "Wind";
    }
    void adjust(){
        System.out.println("Adjusting Wind");
    }
}

class Percussion extends Instrument{
    void play(Note n){
        System.out.println("Percussion.play() "+n);
    }
    String whatObject(){
        return "Percussion";
    }
    void adjust(){
        System.out.println("Adjusting Percussion");
    }
}

class Stringed extends Instrument{
    void play(Note n){
        System.out.println("Stringed.play() "+n);
    }
    String whatObject(){
        return "Stringed";
    }
    void adjust(){
        System.out.println("Adjusting Stringed");
    }
}

class Brass extends Wind{
    void play(Note n){
        System.out.println("Brass.play() "+n);
    }
    void adjust(){
        System.out.println("Adjusting Brass");
    }
}

class Woodwind extends Wind{
    void play(Note n){
        System.out.println("Woodwind.play() "+n);
    }
    String whatObject(){
        return "Woodwind";
    }
}

class Music{
    public static void tune(Instrument i){
        i.play(Note.MIDDLE_A);
    }
    public static void main(String[] args) {
        Music.tune(new Brass());
        //因Brass未覆写toString()所以直接用Instrument里的toString()
        System.out.println(new Brass());
    }
}
/*print
Brass.play() MIDDLE_A
Instrument*/